package com.flute.framework.index.fieldbuilder;

import java.io.Serializable;

public class ScoreMap implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 4773533750097941787L;
	private int[] keys;
	private float[] scores;

	public ScoreMap() {

	}

	public boolean contans(int key) {
		if (keys == null) {
			return false;
		}
		for (int i = 0; i < keys.length; i++) {
			if (keys[i] == key) {
				return true;
			}
		}

		return false;
	}

	public float getScore(int key) {
		if (keys == null) {
			return 0;
		}
		for (int i = 0; i < keys.length; i++) {
			if (keys[i] == key) {
				return scores[i];
			}
		}

		return 0;
	}

	public byte[] toBytes() {
		if (keys != null) {
			byte[] bs = new byte[5 * keys.length];
			for (int i = 0; i < keys.length; i++) {
				bs[i * 5] = Integer.valueOf(keys[i]).byteValue();
				byte[] fbs = floatToBytes(scores[i]);
				for (int j = 0; j < fbs.length; j++) {
					bs[i * 5 + j + 1] = fbs[j];
				}
			}

			return bs;
		} else {
			return new byte[0];
		}
	}

	public static ScoreMap byteToScoreMap(byte[] bs) {
		bs = getValidBytes(bs);
		if (bs == null || bs.length == 0) {
			return new ScoreMap();
		} else {
			ScoreMap sm = new ScoreMap();
			int length = bs.length / 5;
			if (length > 0) {
				for (int i = 0; i < length; i++) {
					byte[] fbs = new byte[4];
					for (int j = 0; j < 4; j++) {
						fbs[j] = bs[i * 5 + j + 1];
					}
					sm.addScore(bs[i * 5], bytesToFloat(fbs));
				}
			}

			return sm;
		}
	}

	private static byte[] getValidBytes(byte[] bs) {
		if (bs == null || bs.length == 0) {
			return new byte[0];
		}

		int end = bs.length - 1;
		for (int i = bs.length - 1; i >= 0; i--) {
			if (bs[i] != 0) {
				end = i;
				break;
			}
		}

		if ((end + 1) % 5 != 0) {
			end = (end + 1) / 5 * 5 + 4;
		}

		byte[] nbs = new byte[end + 1];
		for (int i = 0; i < Math.min(bs.length, end+1); i++) {
			nbs[i] = bs[i];
		}

		return nbs;
	}

	private byte[] floatToBytes(float f) {
		int count = Float.floatToIntBits(f);
		byte[] bs = new byte[4];
		bs[0] = (byte) (count >> 24);
		bs[1] = (byte) (count >> 16);
		bs[2] = (byte) (count >> 8);
		bs[3] = (byte) (count);

		return bs;
	}

	private static float bytesToFloat(byte[] bs) {
		int value = ((bs[0] & 0xFF) << 24) | ((bs[1] & 0xFF) << 16)
				| ((bs[2] & 0xFF) << 8) | (bs[3] & 0xFF);
		return Float.intBitsToFloat(value);
	}

	public void addScore(int key, float score) {
		if (keys == null) {
			keys = new int[1];
			scores = new float[1];

			keys[0] = key;
			scores[0] = score;
		} else {
			boolean contains = false;
			for (int i = 0; i < keys.length; i++) {
				if (keys[i] == key) {
					scores[i] = score;
					contains = true;
					break;
				}
			}

			if (!contains) {
				int[] nks = new int[keys.length + 1];
				float[] nss = new float[scores.length + 1];

				for (int i = 0; i < keys.length; i++) {
					nks[i] = keys[i];
					nss[i] = scores[i];
				}

				nks[keys.length] = key;
				nss[keys.length] = score;

				this.keys = nks;
				this.scores = nss;
			}
		}
	}
}
